package com.songlanyun.modules.category.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.drive.Validator;
import com.songlanyun.common.enums.HouniaoConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.HouniaoApiUtil;
import com.songlanyun.common.utils.RedisUtils;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.common.validator.group.AddGroup;
import com.songlanyun.common.validator.group.UpdateGroup;
import com.songlanyun.modules.exception.GoodsExceptionEnum;
import com.songlanyun.modules.group.entity.ProductGoodsGroupEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.category.dao.SystemProductCategoryDao;
import com.songlanyun.modules.category.entity.SystemProductCategoryEntity;
import com.songlanyun.modules.category.service.SystemProductCategoryService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Nullable;


/**
 * 平台商品分类
 */
@Service("systemProductCategoryService")
public class SystemProductCategoryServiceImpl extends ServiceImpl<SystemProductCategoryDao, SystemProductCategoryEntity> implements SystemProductCategoryService {

    @Autowired
    private SystemProductCategoryService systemProductCategoryService;


    @Autowired
    private HouniaoApiUtil houniaoApiUtil;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 平台创建商品分类
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public SystemProductCategoryEntity create(SystemProductCategoryEntity entity) {
        ValidatorUtils.validateEntity(entity, AddGroup.class);
        validateNameExists(entity);
        validateParent(entity.getParentId());

        this.baseMapper.insert(entity);
        return entity;
    }

    /**
     * 平台修改商品分类
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public SystemProductCategoryEntity modify(SystemProductCategoryEntity entity) {
        ValidatorUtils.validateEntity(entity, UpdateGroup.class);
        validateExists(entity.getId());
        validateNameExists(entity);
        validateUpdateParentSafe(entity);

        this.baseMapper.updateById(entity);
        return this.getById(entity.getId());
    }

    /**
     * 平台删除商品分类
     *
     * @param id
     */
    @Override
    @Transactional
    public void remove(Long id) {
        validateRemoveSafe(id);
        this.removeById(id);
    }


    /**
     * 验证商品分类是否存在
     *
     * @param id
     */
    public void validateExists(Long id) {
        SystemProductCategoryEntity entity = this.getById(id);
        if (entity == null) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_NOT_EXISTS);
        }
    }

    /**
     * 如果新增时设置的父级对象不存在报错,
     * 如果新增加选择的父级是二级报错，只能有两级分类
     *
     * @param parentId
     */
    private void validateParent(Long parentId) {
        if (parentId == 0) return;
        SystemProductCategoryEntity entity = this.getById(parentId);
        if (entity == null) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_PARENT_NOT_EXISTS);
        }

        if (entity.getParentId() > 0) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_SECOND_SAFE);
        }
    }


    /**
     * 1、商品分类的父级不存在报错
     * 2、商品分类的父级还有父级报错
     * 3、自己有父级，同时自己还有下级分类报错，系统只需要两级
     *
     * @param entity
     */
    private void validateUpdateParentSafe(SystemProductCategoryEntity entity) {
        /**
         * 如果要修改的父级属性不大于0
         */
        if (entity.getParentId() > 0) {
            //如果自己还有下级，说明现在成了三级，但是系统只需要两级，所以要报错

            SystemProductCategoryEntity parent = this.getById(entity.getParentId());
            if (parent == null) {
                throw new RRException(GoodsExceptionEnum.CATEGORY_PARENT_NOT_EXISTS);
            }

            if (parent.getParentId() > 0) {
                throw new RRException(GoodsExceptionEnum.CATEGORY_SECOND_SAFE);
            }

            if (entity.loadChildren().size() > 0) {
                throw new RRException(GoodsExceptionEnum.CATEGORY_SELECT_SELF);
            }

            if (entity.getParentId() == entity.getId()) {
                throw new RRException(GoodsExceptionEnum.CATEGORY_SECOND_SAFE);
            }
        }
    }

    /**
     * 查询分类下面的子分类
     *
     * @param parentId
     * @return
     */
    @Override
    public List<SystemProductCategoryEntity> getChildren(Long parentId) {
        QueryWrapper<SystemProductCategoryEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId);
        List<SystemProductCategoryEntity> systemProductCategoryEntities = this.baseMapper.selectList(queryWrapper);
        return systemProductCategoryEntities;
    }

    /**
     * 查询一级分类
     *
     * @return
     */
    @Override
    public List<SystemProductCategoryEntity> getFirstCategory() {
        return this.getChildren(0L);
    }

    public static final String REDIS_KEY_HOUNIAO_CATEGORIES = "HOUNIAO_CATEGORIES";

    /**
     * 为移动客户端询商品分类列表，如果指定了父分类ID，则查询此父分类下的子分类列表。
     * @param parentId 父分类ID
     * @return 移动客户端询商品分类列表，
     */
    @Override
    public List<SystemProductCategoryEntity> homeRecommend(@Nullable Long parentId) {
        /*
        return this.baseMapper.selectList(
                new LambdaQueryWrapper<SystemProductCategoryEntity>()
                        .eq(SystemProductCategoryEntity::getRecommend, true)
                        .orderByAsc(SystemProductCategoryEntity::getOrderIndex)
        );
         */

        //从候鸟接口中获取商品分类
        List<SystemProductCategoryEntity> categoryEntityList = new ArrayList<>();
        JSONObject reqParams = new JSONObject();
        reqParams.put("pid", 1);
        JSONObject houniaoResponse = null;
        String houniaoCategoryJson = redisUtils.getCacheObject(REDIS_KEY_HOUNIAO_CATEGORIES);
        if(StringUtils.isEmpty(houniaoCategoryJson)) {
            houniaoResponse = houniaoApiUtil.client(reqParams, HouniaoConstant.CATEGORY_LIST.getUrl());
            redisUtils.set(REDIS_KEY_HOUNIAO_CATEGORIES, houniaoResponse.toJSONString());
        } else {
            houniaoResponse = JSONObject.parseObject(houniaoCategoryJson);
        }
        JSONArray categoryData = houniaoResponse.getJSONArray("data");
        if(categoryData != null && !categoryData.isEmpty()) {
            if(parentId == null) {
                for (int i = 0; i < categoryData.size(); i++) {
                    JSONObject categoryJSON = categoryData.getJSONObject(i);
                    if (categoryJSON == null) continue;

                    // TODO 临时加的需求，平台展示不需要展示全部的候鸟分类，只需要展示如下分类
                    // TODO 母婴用品，美妆护肤，个人护理，营养保健，家用电器，休闲食品，医疗保健，珠宝首饰，家居日用，数码电子
                    String categoryName = categoryJSON.getString("name");
                    if(!com.alibaba.druid.util.StringUtils.equals(categoryName,"母婴用品")
                            && !com.alibaba.druid.util.StringUtils.equals(categoryName,"美妆护肤") && !com.alibaba.druid.util.StringUtils.equals(categoryName,"个人护理") && !com.alibaba.druid.util.StringUtils.equals(categoryName,"营养保健")
                            && !com.alibaba.druid.util.StringUtils.equals(categoryName,"家用电器") && !com.alibaba.druid.util.StringUtils.equals(categoryName,"休闲食品") && !com.alibaba.druid.util.StringUtils.equals(categoryName,"医疗保健")
                            && !com.alibaba.druid.util.StringUtils.equals(categoryName,"珠宝首饰") && !com.alibaba.druid.util.StringUtils.equals(categoryName,"家居日用") && !StringUtils.equals(categoryName,"数码电子")) {
                        continue;
                    }

                    SystemProductCategoryEntity categoryEntity = convertJSONObjectToSystemProductCategoryEntity(categoryJSON, i);
                    categoryEntityList.add(categoryEntity);
                }
            } else {
                for (int i = 0; i < categoryData.size(); i++) {
                    JSONObject categoryJSON = categoryData.getJSONObject(i);
                    if (categoryJSON == null) continue;

                    // TODO 临时加的需求，平台展示不需要展示全部的候鸟分类，只需要展示如下分类
                    // TODO 母婴用品，美妆护肤，个人护理，营养保健，家用电器，休闲食品，医疗保健，珠宝首饰，家居日用，数码电子
                    String categoryName = categoryJSON.getString("name");
                    if(!StringUtils.equals(categoryName,"母婴用品")
                            && !StringUtils.equals(categoryName,"美妆护肤") && !StringUtils.equals(categoryName,"个人护理") && !StringUtils.equals(categoryName,"营养保健")
                            && !StringUtils.equals(categoryName,"家用电器") && !StringUtils.equals(categoryName,"休闲食品") && !StringUtils.equals(categoryName,"医疗保健")
                            && !StringUtils.equals(categoryName,"珠宝首饰") && !StringUtils.equals(categoryName,"家居日用") && !StringUtils.equals(categoryName,"数码电子")) {
                        continue;
                    }

                    Long id = categoryJSON.getLong("id");
                    if(!Objects.equals(id, parentId)) continue;

                    JSONArray childrenArray = categoryJSON.getJSONArray("children");
                    if(childrenArray != null && !childrenArray.isEmpty()) {
                        for (int j = 0; j < childrenArray.size(); j++) {
                            JSONObject childJSON = childrenArray.getJSONObject(j);
                            SystemProductCategoryEntity categoryEntity = convertJSONObjectToSystemProductCategoryEntity(childJSON, j);
                            categoryEntityList.add(categoryEntity);
                        }
                    }
                }
            }
        }
        return categoryEntityList;
    }

    private SystemProductCategoryEntity convertJSONObjectToSystemProductCategoryEntity(JSONObject jsonObject, int orderIndex) {
        SystemProductCategoryEntity categoryEntity = new SystemProductCategoryEntity();
        categoryEntity.setId(jsonObject.getLong("id"));
        categoryEntity.setParentId(jsonObject.getLong("pid"));
        categoryEntity.setName(jsonObject.getString("name"));
        categoryEntity.setCoverImage(jsonObject.getString("image"));
        categoryEntity.setOrderIndex(orderIndex);
        return categoryEntity;
    }

    /**
     * 验证分类的名称不能重复
     *
     * @param entity
     */
    private void validateNameExists(SystemProductCategoryEntity entity) {
        SystemProductCategoryEntity target = this.baseMapper.getByName(entity.getName());
        if (target != null && !target.equals(entity)) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_NAME_REPEAT);
        }
    }


    /**
     * 删除分组时的安全验证
     * 要删除的分组不存在不能删除
     * 下面还有子分组的不能删除
     *
     * @param id
     */
    private void validateRemoveSafe(Long id) {
        SystemProductCategoryEntity entity = this.getById(id);
        if (entity == null) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_NOT_EXISTS);
        }

        if (entity.loadChildren().size() > 0) {
            throw new RRException(GoodsExceptionEnum.CATEGORY_REMOVE_SAFE);
        }
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Long parentId = MapUtil.getLong(params, "parent_id");
        IPage<SystemProductCategoryEntity> page = this.page(
                new Query<SystemProductCategoryEntity>().getPage(params),
                new LambdaQueryWrapper<SystemProductCategoryEntity>()
                        .eq(ObjectUtil.isNotNull(parentId), SystemProductCategoryEntity::getParentId, parentId)
                        .orderByAsc(SystemProductCategoryEntity::getOrderIndex)
        );

        return new PageUtils(page);
    }


    private List<Map<String, Object>> makeDepartmentTree(List<SystemProductCategoryEntity> categoryEntities, long parentId) {
        List<Map<String, Object>> list = new ArrayList<>();

        for (SystemProductCategoryEntity categoryEntity : categoryEntities) {
            if (categoryEntity.getParentId() == parentId) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("id", categoryEntity.getId());
                map.put("name", categoryEntity.getName());
                map.put("parent_id", categoryEntity.getParentId());
                map.put("order_index", categoryEntity.getOrderIndex());
                map.put("recommend", categoryEntity.getRecommend());
                map.put("children", makeDepartmentTree(categoryEntities, categoryEntity.getId()));
                list.add(map);
            }
        }

        CollectionUtil.sort(list, (o1, o2) -> {
            int orderIndex1 = (int) o1.get("order_index");
            int orderIndex2 = (int) o2.get("order_index");
            return Integer.compare(orderIndex1, orderIndex2);
        });

        return list;
    }

    /**
     * 查询所有商品分类
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> getAllCategory() {
        /*
        List<SystemProductCategoryEntity> list = this.list(
                new LambdaQueryWrapper<SystemProductCategoryEntity>()
                        .orderByAsc(SystemProductCategoryEntity::getOrderIndex)
        );

        return makeDepartmentTree(list, 0);
         */

        //从候鸟接口中获取商品分类
        JSONObject reqParams = new JSONObject();
        JSONObject houniaoResponse = null;
        String houniaoCategoryJson = redisUtils.getCacheObject(REDIS_KEY_HOUNIAO_CATEGORIES);
        if(StringUtils.isEmpty(houniaoCategoryJson)) {
            houniaoResponse = houniaoApiUtil.client(reqParams, HouniaoConstant.CATEGORY_LIST.getUrl());
            redisUtils.set(REDIS_KEY_HOUNIAO_CATEGORIES, houniaoResponse.toJSONString());
        } else {
            houniaoResponse = JSONObject.parseObject(houniaoCategoryJson);
        }
        JSONArray categoryData = houniaoResponse.getJSONArray("data");
        List<Map<String, Object>> mapList = convertJSONArrayToMapList(categoryData, 0);
        if(categoryData != null && !categoryData.isEmpty()) {
            for(int i = 0; i < mapList.size(); i++) {
                Map<String, Object> map = mapList.get(i);
                if(map == null) continue;

                JSONObject categoryJSON = categoryData.getJSONObject(i);
                JSONArray childrenArray = categoryJSON.getJSONArray("children");
                List<Map<String, Object>> children = convertJSONArrayToMapList(childrenArray, 1);
                map.put("children", children);
            }
        }
        //兑换区查询
        SystemProductCategoryEntity systemProductCategory = systemProductCategoryService.getOne(new LambdaQueryWrapper<SystemProductCategoryEntity>()
                .eq(SystemProductCategoryEntity::getName, "兑换区"));

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("id", systemProductCategory.getId());
        map.put("name",systemProductCategory.getName());
        map.put("parent_id", systemProductCategory.getParentId());
        map.put("cover_image", systemProductCategory.getCoverImage());
        map.put("order_index", systemProductCategory.getOrderIndex());
        map.put("recommend", true);
        mapList.add(map);
        return mapList;
    }

    private List<Map<String, Object>> convertJSONArrayToMapList(JSONArray jsonArray, int level) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        if(jsonArray != null && !jsonArray.isEmpty()) {
            for(int i = 0; i < jsonArray.size(); i++) {
                JSONObject categoryJSON = jsonArray.getJSONObject(i);
                if(categoryJSON == null) continue;

                if(level == 0){
                    // TODO 临时加的需求，平台展示不需要展示全部的候鸟分类，只需要展示如下分类
                    // TODO 母婴用品，美妆护肤，个人护理，营养保健，家用电器，休闲食品，医疗保健，珠宝首饰，家居日用，数码电子
                    String categoryName = categoryJSON.getString("name");
                    if(!StringUtils.equals(categoryName,"母婴用品")
                            && !StringUtils.equals(categoryName,"美妆护肤") && !StringUtils.equals(categoryName,"个人护理") && !StringUtils.equals(categoryName,"营养保健")
                            && !StringUtils.equals(categoryName,"家用电器") && !StringUtils.equals(categoryName,"休闲食品") && !StringUtils.equals(categoryName,"医疗保健")
                            && !StringUtils.equals(categoryName,"珠宝首饰") && !StringUtils.equals(categoryName,"家居日用") && !StringUtils.equals(categoryName,"数码电子")) {
                        continue;
                    }
                }

                Map<String, Object> map = new LinkedHashMap<>();
                map.put("id", categoryJSON.get("id"));
                map.put("name", categoryJSON.get("name"));
                map.put("parent_id", categoryJSON.get("pid"));
                map.put("cover_image", categoryJSON.get("image"));
                map.put("order_index", i);
                map.put("recommend", true);
                mapList.add(map);
            }
        }
        return mapList;
    }
}

